package org.hepeng.workx.mybatis.mapper;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.session.Configuration;
import org.hepeng.workx.exception.ApplicationRuntimeException;
import org.hepeng.workx.extension.XPoint;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author he peng
 */

@XPoint("hibernate")
public interface MappedStatementSupplier {

    void initialize(TableMapMetadata tableMapMetaData, MapperBuilderAssistant assistant , Configuration configuration);

    @Supplier
    void supplyAllColumnInsertStatement();

    @Supplier
    void supplySelectiveColumnInsertStatement();

    @Supplier
    void supplyAllColumnUpdateByIdStatement();

    @Supplier
    void supplySelectiveUpdateByIdStatement();

    @Supplier
    void supplyDeleteByIdAtPhysicalStatement();

    @Supplier
    void supplyDeleteByIdAtLogicalStatement();

    @Supplier
    void supplySelectByIdStatement();

    @Supplier
    void supplySelectByDynamicWhereStatement();

    default void triggerAllSupplier() {
        List<Method> supplierMethods = MethodUtils.getMethodsListWithAnnotation(MappedStatementSupplier.class, Supplier.class);
        if (CollectionUtils.isNotEmpty(supplierMethods)) {
            supplierMethods.forEach(method -> {
                try {
                    method.invoke(this);
                } catch (Exception e) {
                    throw new ApplicationRuntimeException(e);
                }
            });
        }
    }

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    @interface Supplier {}

}
